import random
import re
from collections import defaultdict
class Player:
    def __init__(self, num, role):
        self.name = f"玩家{num}"
        self.num = num  # 固定序号
        self.role = role
        self.alive = True
        self.saved = False      # 女巫解药标记
        self.poisoned = False   # 女巫毒药标记
        self.cursed = False     # 乌鸦诅咒标记
    def __repr__(self):
        return f"{self.num}.{self.name}（{self.role}）"
class WerewolfGame:
    def __init__(self):
        self.players = []
        self.day = 1
        self.witch_has_potion = True  # 女巫解药
        self.witch_has_poison = True  # 女巫毒药
        self.seer_checked = set()  # 预言家已查验过的玩家
        self.guard_protected = set()  # 守卫已守护过的玩家
        self.guard_broken = False  # 守卫盾是否已破
        self.cursed_player = None  # 乌鸦诅咒的玩家
        self.mode = self.choose_mode()  # 选择游戏模式
        self.assign_roles()
        self.last_night_deaths = []  # 存储昨夜死亡信息
        self.has_witch = "女巫" in self.mode["gods"]
        # 新增：骑士技能使用标记（用于8/9人局限制）
        self.knight_skill_used = False  
    def choose_mode(self):
        print("===== 选择游戏模式 =====")
        print("一、6人局：2狼2民2神（守卫+预言家）")
        print("二、8人局：3狼2民3神（守卫+预言家+骑士）")
        print("三、9人局：3狼（2普狼1狼王）2民4神（守卫+骑士+预言家+乌鸦）")
        print("四、12人局：4狼（3普狼1狼王）4民4神（守卫+预言家+猎人+女巫）")      
        while True:
            choice = input("请选择模式（输入序号一/二/三/四）：")
            if choice == "一":
                return {"player_count":6, "wolves":2, "civilian":2, "gods":["守卫", "预言家"]}
            elif choice == "二":
                return {"player_count":8, "wolves":3, "civilian":2, "gods":["守卫", "预言家", "骑士"]}
            elif choice == "三":
                return {"player_count":9, "wolves":2, "wolf_king":1, "civilian":2, "gods":["守卫", "预言家", "骑士", "乌鸦"]}
            elif choice == "四":
                return {"player_count":12, "wolves":3, "wolf_king":1, "civilian":4, "gods":["守卫", "预言家", "猎人", "女巫"]}
            else:
                print("输入无效，请重新选择！")
    def assign_roles(self):
        roles = []
        roles.extend(['狼人'] * self.mode["wolves"])
        if "wolf_king" in self.mode:
            roles.append('狼王')
        roles.extend(['村民'] * self.mode["civilian"])
        roles.extend(self.mode["gods"])       
        random.shuffle(roles)
        for i in range(self.mode["player_count"]):
            self.players.append(Player(i+1, roles[i]))        
        print("\n===== 身份分配完成 =====")
        for p in self.players:
            print(p)
    def check_alive(self, show=True):
        alive = [p for p in self.players if p.alive]
        if show:
            print("\n当前存活玩家：")
            for p in sorted(alive, key=lambda x: x.num):
                print(p)
        return alive
    def wolf_action(self):
        alive = self.check_alive(show=False)
        wolves = [p for p in alive if p.role in ['狼人', '狼王']]
        print("\n===== 狼人行动 =====")
        if not wolves:
            print("无存活狼人，跳过狼人环节")
            return None            
        print("狼人请选择击杀目标（输入玩家序号，0为空刀）：")
        for p in sorted(alive, key=lambda x: x.num):
            print(p)
        while True:
            try:
                choice = int(input("狼人共同选择："))
                if choice == 0:
                    print("狼人选择空刀")
                    return None
                target = next((p for p in alive if p.num == choice), None)
                if target:
                    return target
                else:
                    print("输入无效，请输入存活玩家序号或0（空刀）！")
            except ValueError:
                print("输入无效，请输入数字！")
    def guard_action(self):
        if "守卫" not in self.mode["gods"]:
            return None            
        alive = self.check_alive(show=False)
        guard = next((p for p in alive if p.role == '守卫'), None)
        print("\n===== 守卫行动 =====")
        if not guard:
            print("无存活守卫，跳过守卫环节")
            return None           
        if self.guard_broken:
            print("守卫盾已破，无法进行守护")
            return None            
        print(f"{guard}请选择保护目标（输入玩家序号，0为空守，不可重复守护同一人）：")
        print(f"已守护过的玩家：{[f'玩家{p}' for p in self.guard_protected] if self.guard_protected else '无'}")
        for p in sorted(alive, key=lambda x: x.num):
            status = "（已守护过）" if p.num in self.guard_protected else ""
            print(f"{p}{status}")           
        while True:
            try:
                choice = int(input(f"{guard.name}选择："))
                if choice == 0:
                    print(f"{guard.name}选择空守")
                    return None
                target = next((p for p in alive if p.num == choice), None)
                if not target:
                    print("输入无效，请输入存活玩家序号！")
                elif target.num in self.guard_protected:
                    print("不可重复守护同一玩家，请重新选择！")
                else:
                    self.guard_protected.add(target.num)
                    return target
            except ValueError:
                print("输入无效，请输入数字！")
    def seer_action(self):
        if "预言家" not in self.mode["gods"]:
            return           
        alive = self.check_alive(show=False)
        seer = next((p for p in alive if p.role == '预言家'), None)
        print("\n===== 预言家行动 =====")
        if not seer:
            print("无存活预言家，跳过预言家环节")
            return            
        print(f"{seer}请选择查验目标（输入玩家序号，不可重复查验同一人）：")
        print(f"已查验过的玩家：{[f'玩家{p}' for p in self.seer_checked] if self.seer_checked else '无'}")
        for p in sorted(alive, key=lambda x: x.num):
            status = "（已查验过）" if p.num in self.seer_checked else ""
            print(f"{p}{status}")            
        while True:
            try:
                choice = int(input(f"{seer.name}选择："))
                target = next((p for p in alive if p.num == choice), None)
                if not target:
                    print("输入无效，请输入存活玩家序号！")
                elif target.num in self.seer_checked:
                    print("不可重复查验同一玩家，请重新选择！")
                else:
                    self.seer_checked.add(target.num)
                    result = "狼人" if target.role in ['狼人', '狼王'] else '好人'
                    print(f"查验结果：{target}是{result}")
                    return
            except ValueError:
                print("输入无效，请输入数字！")
    def witch_action(self, wolf_target, guard_target):
        if "女巫" not in self.mode["gods"]:
            return wolf_target           
        alive = self.check_alive(show=False)
        witch = next((p for p in alive if p.role == '女巫'), None)
        print("\n===== 女巫行动 =====")
        if not witch:
            print("无存活女巫，跳过女巫环节")
            return wolf_target            
        if self.witch_has_potion and wolf_target:
            display_target = wolf_target if wolf_target != guard_target else "（未知）"
            target_info = f"{display_target}" if display_target != "（未知）" else display_target
            print(f"今晚被袭击的是：{target_info}")
            use_potion = input(f"{witch.name}是否使用解药？（1.使用 2.不使用）：") == '1'
            if use_potion:
                self.witch_has_potion = False
                wolf_target.saved = True
                print("已使用解药")
        elif self.witch_has_potion:
            print("今晚无袭击目标，无法使用解药")            
        if self.witch_has_poison:
            use_poison = input(f"{witch.name}是否使用毒药？（1.使用 2.不使用）：") == '1'
            if use_poison:
                self.witch_has_poison = False
                print("请选择毒杀目标（输入玩家序号）：")
                for p in sorted(alive, key=lambda x: x.num):
                    print(p)
                while True:
                    try:
                        choice = int(input(f"{witch.name}选择："))
                        target = next((p for p in alive if p.num == choice), None)
                        if target:
                            target.poisoned = True
                            print(f"已对{target}使用毒药")
                            break
                        else:
                            print("输入无效，请输入存活玩家序号！")
                    except ValueError:
                        print("输入无效，请输入数字！")
        else:
            print("毒药已使用完毕")            
        return wolf_target
    def crow_action(self):
        if "乌鸦" not in self.mode["gods"]:
            return            
        alive = self.check_alive(show=False)
        crow = next((p for p in alive if p.role == '乌鸦'), None)
        print("\n===== 乌鸦行动 =====")
        if not crow:
            print("无存活乌鸦，跳过乌鸦环节")
            return            
        print(f"{crow}请选择诅咒目标（输入玩家序号，0为不诅咒）：")
        for p in sorted(alive, key=lambda x: x.num):
            print(p)           
        while True:
            try:
                choice = int(input(f"{crow.name}选择："))
                if choice == 0:
                    print(f"{crow.name}选择不诅咒")
                    self.cursed_player = None
                    return
                target = next((p for p in alive if p.num == choice), None)
                if target:
                    self.cursed_player = target
                    print(f"已对{target}施加诅咒")
                    return
                else:
                    print("输入无效，请输入存活玩家序号或0（不诅咒）！")
            except ValueError:
                print("输入无效，请输入数字！")
    def knight_action(self):
        if "骑士" not in self.mode["gods"]:
            return            
        alive = self.check_alive(show=False)
        knight = next((p for p in alive if p.role == '骑士'), None)
        if not knight:
            return            
        # 核心修改：8/9人局限制骑士技能只能使用一次
        if self.mode["player_count"] in [8, 9]:  # 判断是否为8人或9人局
            if self.knight_skill_used:  # 已使用过技能
                print(f"\n===== 骑士行动 =====")
                print(f"{knight}技能已发动过，8/9人局整场游戏只能发动一次技能")
                return       
        print(f"\n===== 骑士行动 =====")
        use_skill = input(f"{knight}是否发动决斗技能？（1.发动 2.不发动）：") == '1'
        if not use_skill:
            print(f"{knight.name}选择不发动技能")
            return            
        # 技能发动后标记（仅8/9人局）
        if self.mode["player_count"] in [8, 9]:
            self.knight_skill_used = True           
        print("请选择决斗目标（输入玩家序号）：")
        for p in sorted(alive, key=lambda x: x.num):
            if p != knight:
                print(p)                
        while True:
            try:
                choice = int(input(f"{knight.name}选择决斗目标："))
                target = next((p for p in alive if p.num == choice and p != knight), None)
                if target:
                    if target.role in ['狼人', '狼王']:
                        target.alive = False
                        self.last_night_deaths.append(f"{target}被骑士决斗淘汰（狼人）")
                        print(f"{target}是狼人，已被淘汰")
                        if target.role == '狼王':
                            self.handle_wolf_king_skill(target)
                    else:
                        knight.alive = False
                        self.last_night_deaths.append(f"{knight}决斗好人失败，自身淘汰")
                        print(f"{target}是好人，{knight}淘汰")
                    return
                else:
                    print("输入无效，请输入其他存活玩家序号！")
            except ValueError:
                print("输入无效，请输入数字！")
    def night_phase(self):
        print(f"\n===== 第{self.day}天 夜晚 =====")
        alive = self.check_alive()
        if len(alive) <= 1:
            return       
        self.last_night_deaths = []
        guard_target = self.guard_action()
        wolf_target = self.wolf_action()
        self.seer_action()
        self.crow_action()       
        if self.has_witch:
            wolf_target = self.witch_action(wolf_target, guard_target) if wolf_target else None        
        if wolf_target and guard_target and wolf_target == guard_target:
            self.guard_broken = True
            print(f"\n守卫成功守护{wolf_target}，但守卫盾已破")        
        if wolf_target and wolf_target != guard_target and not wolf_target.saved:
            wolf_target.alive = False
            self.last_night_deaths.append(f"{wolf_target}被狼人杀害")        
        if self.has_witch:
            for p in alive:
                if p.poisoned:
                    p.alive = False
                    self.last_night_deaths.append(f"{p}被女巫毒死")        
        for p in self.players:
            p.saved = False
            p.poisoned = False
    def handle_hunter_skill(self, hunter):
        if "猎人" not in self.mode["gods"]:
            return           
        alive = self.check_alive(show=False)
        if not alive:
            return
        print(f"\n{hunter}（猎人）发动技能，选择带走一名玩家：")
        for p in sorted(alive, key=lambda x: x.num):
            print(p)       
        while True:
            try:
                choice = int(input(f"{hunter.name}选择带走："))
                target = next((p for p in alive if p.num == choice), None)
                if target:
                    target.alive = False
                    print(f"{target}被猎人带走")
                    if target.role == '猎人':
                        self.handle_hunter_skill(target)
                    break
                else:
                    print("输入无效，请输入存活玩家序号！")
            except ValueError:
                print("输入无效，请输入数字！")
    def handle_wolf_king_skill(self, wolf_king):
        if "wolf_king" not in self.mode:
            return           
        alive = self.check_alive(show=False)
        if not alive:
            return
        print(f"\n{wolf_king}（狼王）发动技能，选择带走一名玩家：")
        for p in sorted(alive, key=lambda x: x.num):
            print(p)        
        while True:
            try:
                choice = int(input(f"狼王选择带走："))
                target = next((p for p in alive if p.num == choice), None)
                if target:
                    target.alive = False
                    print(f"{target}被狼王带走")
                    break
                else:
                    print("输入无效，请输入存活玩家序号！")
            except ValueError:
                print("输入无效，请输入数字！")
    def vote_phase(self):
        print(f"\n===== 第{self.day}天 白天投票 =====")
        alive = self.check_alive()
        if not alive:
            return None        
        print("\n===== 昨夜死亡情况 =====")
        if not self.last_night_deaths:
            print("昨夜是平安夜")
        else:
            for death in self.last_night_deaths:
                print(f"- {death}")
                match = re.search(r'玩家(\d+)', death)
                if match:
                    player_num = int(match.group(1))
                    hunter = next((p for p in self.players if p.num == player_num and p.role== '猎人'), None)
                    if hunter:
                        self.handle_hunter_skill(hunter)
                    wolf_king = next((p for p in self.players if p.num == player_num and p.role == '狼王'), None)
                    if wolf_king:
                        self.handle_wolf_king_skill(wolf_king)       
        self.knight_action()     
        alive = self.check_alive(show=False)
        if not alive:
            return None
        print("\n===== 等待确认天亮 =====")
        input("请输入任意内容继续白天环节...")
        def conduct_vote(candidates):
            print("\n投票目标列表（输入玩家序号，0为弃权）：")
            for p in sorted(candidates, key=lambda x: x.num):
                print(p)
            votes = defaultdict(int)
            for voter in sorted(alive, key=lambda x: x.num):
                print(f"\n请{voter}投票：")
                while True:
                    try:
                        choice = int(input(f"{voter.name}的选择："))
                        if choice == 0:
                            print(f"{voter.name}选择弃权")
                            break
                        target = next((p for p in candidates if p.num == choice), None)
                        if target:
                            votes[target] += 1
                            print(f"{voter.name}投票给了{target.name}")
                            break
                        else:
                            print("输入无效，请输入候选玩家序号或0（弃权）！")
                    except ValueError:
                        print("输入无效，请输入数字！")  
            if self.cursed_player and self.cursed_player in candidates:
                votes[self.cursed_player] += 1
                print(f"\n乌鸦诅咒生效，{self.cursed_player}额外获得1票")
            return votes
        candidates = alive.copy()
        放逐目标 = None
        while True:
            votes = conduct_vote(candidates)
            total_votes = sum(votes.values())
            if total_votes == 0:
                print("\n所有人都弃权，本轮无人被放逐")
                break  
            max_votes = max(votes.values())
            if max_votes < 3:
                print(f"\n最高票数为{max_votes}票（不足3票），本轮无人被放逐")
                break 
            top_candidates = [p for p in candidates if votes[p] == max_votes]
            if len(top_candidates) == 1:
                放逐目标 = top_candidates[0]
                break
            else:
                print(f"\n平票！{[p.name for p in top_candidates]}均为{max_votes}票，将对这些玩家重新投票")
                candidates = top_candidates
        if 放逐目标:
            放逐目标.alive = False
            print(f"\n===== 放逐结果 =====")
            print(f"- {放逐目标}以{max_votes}票被放逐")
            if 放逐目标.role == '猎人':
                self.handle_hunter_skill(放逐目标)
            if 放逐目标.role == '狼王':
                self.handle_wolf_king_skill(放逐目标)
        else:
            print("\n===== 放逐结果 =====")
            print("- 本轮无人被放逐")
        print("\n===== 等待进入下一夜 =====")
        input("请输入任意内容继续...")
        return 放逐目标
    def check_winner(self):
        alive = self.check_alive(show=False)
        wolves = [p for p in alive if p.role in ['狼人', '狼王']]
        if not wolves:
            return "村民阵营胜利！"
        villagers = len(alive) - len(wolves)
        if len(wolves) >= villagers:
            return "狼人阵营胜利！"
        return None
    def start(self):
        print("===== 狼人杀游戏开始 =====")
        while True:
            self.night_phase()
            winner = self.check_winner()
            if winner:
                print(f"\n{winner}")
                break
            self.vote_phase()
            winner = self.check_winner()
            if winner:
                print(f"\n{winner}")
                break
            self.day += 1
            self.cursed_player = None
if __name__ == "__main__":
    game = WerewolfGame()
    game.start()
    